﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Configuration;
using System.Web;
using System.Collections;

namespace AmazonAssociatesAPILinqtoXML
{
    /// <summary>
    /// Pulls XML data from Amazon Associates API
    /// </summary>
    public class AmazonData
    {
        #region Public Properties
        /// <summary>
        /// Root element has a namespace, which must be added before getting elements
        /// </summary>
        private static XNamespace ns
        {
            get
            {
                return "http://webservices.amazon.com/AWSECommerceService/2009-03-31";

            }
        }

        /// <summary>
        /// Returns an instance of the Amazon URL Class to get the XML Files
        /// </summary>
        public AmazonURLClass amazonURLClass
        {
            get
            {
                return new AmazonURLClass();
            }
        }

        /// <summary>
        /// No picture image
        /// </summary>
        private static string NoPicture
        {
            get
            {
                return "http://teamportfolios.com/images/no-avatar-small.png";
            }
        }
        #endregion

        /// <summary>
        /// Parses the XML data based on the location of an XML file
        /// </summary>
        /// <param name="requestUrl"></param>
        /// <returns></returns>
        public List<AmazonStrongType> ParseData(string requestUrl)
        {
            //Query Amazon's XML file for products
            try
            {
                XElement tags = XElement.Load(requestUrl);
                var groups = (from book in tags.Descendants(ns + "Item") // Return all nodes with the word "Item" in it
                              let bookAttributes = book.Element(ns + "ItemAttributes") //In each Item node, get the "ItemAttributes" node
                              let offerAttributes = book.Element(ns + "OfferSummary") //Get the Offer Summary Node
                              let mediumImageAttributes = book.Element(ns + "MediumImage")
                              let smallImageAttributes = book.Element(ns + "SmallImage")
                              let largeImage = book.Element(ns + "LargeImage")

                              //Notice how I get each picture's URL here
                              let lI = ((string)largeImage.Element(ns + "URL"))
                              let mI = ((string)mediumImageAttributes.Element(ns + "URL"))
                              let sI = ((string)smallImageAttributes.Element(ns + "URL"))
                              let lowestNewPrice = offerAttributes.Element(ns + "LowestNewPrice") //Within the Offer Summary Node, get the Lowest New Price node
                              orderby ((int)book.Element(ns + "SalesRank")) ascending

                              select new AmazonStrongType
                              {
                                  ASIN = ((string)book.Element(ns + "ASIN")),
                                  SalesRank = ((int)book.Element(ns + "SalesRank")),
                                  ProductName = ((string)bookAttributes.Element(ns + "Title")),
                                  
                                  //I then check if the picutre if null or empty
                                  // and if null or empty, return a image saying no picture available
                                  // else return the image
                                  LargeProductImageUrl = (!String.IsNullOrEmpty(lI)) ? lI : NoPicture,
                                  MediumProductImageUrl = (!String.IsNullOrEmpty(mI)) ? mI : NoPicture,
                                  SmallProductImageUrl = (!String.IsNullOrEmpty(sI)) ? sI : NoPicture,
                                  
                                  DetailPageUrl = ((string)book.Element(ns + "DetailPageURL")),
                                  Manufacturer = ((string)bookAttributes.Element(ns + "Manufacturer")),
                                  ProductPrice = ParsePrice(lowestNewPrice)
                              });
                if (groups.Count() > 0)
                {
                    return groups.ToList();

                }
                else
                {
                    return null;
                    throw new Exception("No data.");
                }
            }
            catch (NullReferenceException ex)
            {
                return null;
                throw new NullReferenceException("The data has returned no results. Please check and see if you've filled out your AwsAccessKeyID and your AwsSecretAccessKey. Please also ensure that your search words are spelled correctly");
            }
            catch (HttpException ex)
            {
                return null;
                throw new HttpException("An http exception has occured");
            }
            catch (Exception ex)
            {
                return null;
                throw new Exception("A general error has occurred. Please ensure that the URL going into the method is correct. Check the code in the class library.");
            }
        }

        /// <summary>
        /// Parses data for similarity look-up, so there are no pictures
        /// </summary>
        /// <param name="requestUrl"></param>
        /// <returns></returns>
        public List<AmazonStrongType> SimilarityParseData(string requestUrl)
        {
            //Query Amazon's XML file for products
            try
            {
                XElement tags = XElement.Load(requestUrl);
                var groups = (from book in tags.Descendants(ns + "Item") // Return all nodes with the word "Item" in it
                              let bookAttributes = book.Element(ns + "ItemAttributes") //In each Item node, get the "ItemAttributes" node
                              let offerAttributes = book.Element(ns + "OfferSummary") //Get the Offer Summary Node
                              let lowestNewPrice = offerAttributes.Element(ns + "LowestNewPrice") //Within the Offer Summary Node, get the Lowest New Price node
                              orderby ((int)book.Element(ns + "SalesRank")) ascending

                              select new AmazonStrongType
                              {
                                  ASIN = ((string)book.Element(ns + "ASIN")),
                                  SalesRank = ((int)book.Element(ns + "SalesRank")),
                                  ProductName = ((string)bookAttributes.Element(ns + "Title")),
                                  DetailPageUrl = ((string)book.Element(ns + "DetailPageURL")),
                                  Manufacturer = ((string)bookAttributes.Element(ns + "Manufacturer")),
                                  ProductPrice = ParsePrice(lowestNewPrice)
                              });
                if (groups.Count() > 0)
                {
                    return groups.ToList();

                }
                else
                {
                    return null;
                    throw new Exception("No data.");
                }
            }
            catch (NullReferenceException ex)
            {
                return null;
                throw new NullReferenceException("The data has returned no results. Please check and see if you've filled out your AwsAccessKeyID and your AwsSecretAccessKey. Please also ensure that your search words are spelled correctly");
            }
            catch (HttpException ex)
            {
                return null;
                throw new HttpException("An http exception has occured");
            }
            catch (Exception ex)
            {
                return null;
                throw new Exception("A general error has occurred. Please ensure that the URL going into the method is correct. Check the code in the class library.");
            }
        }

        private decimal ParsePrice(XElement priceElement)
        {
            return Convert.ToDecimal(((string)priceElement.Element(ns + "FormattedPrice")).Replace("$", String.Empty));
        }
    }
}
